import numpy as np

_CONV_STRING = {'FA','a', 'b', 'c', 'd'}
_POOL_STRING = {'e', 'f', 'g', 'h'}

def decode_flow(individuals,Neural_nodes,nodes,_conv,_pool):
    # getattr(obj, attribute_name)
    matrixs_nns = []
    matrix_nodes = []
    real_nns = []
    for individual in individuals:
        matrix_n= fill_matrix(individual,Neural_nodes,nodes)
        matrixs_nns.append(matrix_n)

    for matrix in matrixs_nns:
        matrix_node = np.zeros((Neural_nodes, Neural_nodes + 2), dtype=object)

        real_nn,_matrix = get_struc(matrix,matrix_node,_conv,_pool,nodes)
        real_nns.append(real_nn)
        matrix_nodes.append(_matrix)
    # 返回一个携带了信息流的列表 和标识其连接信息的矩阵
    return real_nns,matrix_nodes

def fill_matrix(individual,Neural_nodes,nodes):
    matrixs_nn = np.zeros((Neural_nodes, Neural_nodes + 2), dtype=object)
    temp = 0
    for i in range(Neural_nodes):
        col = 0
        for j in range(temp, temp + i + 2):
            matrixs_nn[i][col] = individual[j]
            col += 1
        temp = temp+i+2
    return matrixs_nn

def get_struc(matrix,matrix_node,_conv,_pool,nodes):
    real_nn = []
    # 用作标识矩阵 0表示无连接 [-1,1]表示有连接 -1表示池化 1表示卷积 2表示节点
    matrix_temp = matrix_node
    for i in range(matrix.shape[0]):
        temp_nn = []
        for j in range(matrix.shape[1]):  # 遍历列
            if matrix[i][j] == 0:
                matrix_temp[i][j] = 2
                break
            if matrix[i][j] in _CONV_STRING:
                nn_of,flag = get_output_nn(matrix[i][j],_conv,j,real_nn)
                temp_nn.append(nn_of)
                matrix_temp[i][j] = flag
            elif matrix[i][j] in _POOL_STRING:
                nn_of, flag = get_output_nn(matrix[i][j], _pool, j, real_nn)
                temp_nn.append(nn_of)
                # matrix_temp[i][j] = flag
                matrix_temp[i][j] = flag if flag==0 else -1
        temp_nn.append(nodes[i])
        real_nn.append(temp_nn)
    return real_nn,matrix_temp

def get_row_nn(operator, name):
    op_nn = getattr(operator, name)
    if isinstance(op_nn, bool):
        return False
    return op_nn

def get_output_nn(flow,operator,j,real_nn):
    if isinstance(get_row_nn(operator,flow),bool) or get_row_nn(operator,flow)=="NoConnection":
        return False,0
    else:
        return get_row_nn(operator, flow), 1
        # 暂时不需要获取上一层的输出
        # if j<=1:
        #     return get_row_nn(operator,flow),1
        # else:
        #     return get_row_nn(operator,flow),1

if __name__=="__main__":
    print("this is utils")